package org.arga.empresa.repository;

import java.util.Collection;

/**
 * Generic contract for all repository contracts (DAOs).
 * 
 * <p>Following the semantics of "unchecked" exceptions, all operations do not
 * throw any exceptions on errors as it is expected that the IoC container 
 * managing the lifecycle of implementations, ensure proper Exceptions management
 * (e.g. Spring's DataAccessException), and potentially even handling of the
 * same.
 * 
 * @author aflores@arga-inc.com
 * @since Dec 22, 2009 11:44:30 PM
 * @param <PK> the Primary Identifier, typically the id.
 * @param <T> the Entity type of this generic repository. 
 */
public interface GenericRepository<PK, T> {

	/**
	 * Creates a new entity in the repository. This is done using the argument
	 * passed. If this entity is null, this operation is silently ignored, 
	 * otherwise the <i>persistent</i> entity is returned. 
	 * <p>Note that <i>persistent</i> entities typically reflects some additional
	 * information than <i>detached</i> and <i>transient</i> entities which is 
	 * relevant only to the repository implementation. 
	 * 
	 * @param entity the entity to create.
	 * @return the entity that was just persisted. Null is returned if the 
	 * parameter passed was null.
	 */
	public T createEntity(T entity);
	
	/**
	 * Updates the entity specified in the parameter. If the entity passed is null,
	 * this operation is silently ignored otherwise the operation ensures that an
	 * update call is made in the persistent context.
	 * <p>Keep in mind that an <b>update</b> operation is meant to be executed on
	 * <i>persistent</i> or <i>detached</i> entities. Furthermore, updates on 
	 * <i>persistent</i> entities are not necessarily needed (e.g. JPA) as this 
	 * is typically handled by the "dirty" context entity check at the end of a 
	 * transaction, thus ensuring proper updates to occur at the end of a call.
	 * Implementations of this contract are responsible for properly executing this
	 * method within the context of the persistent technology of choice.
	 * @param entity the entity to update (e.g. merge, update). 
	 */
	public void updateEntity(T entity);
	
	/**
	 * Removes the entity from the repository (persistent context). If the parameter
	 * is null, this operation is silently ignored. Furthermore, if there's no 
	 * entity associated with the given identifier, this operation is also 
	 * silently ignored.
	 * <p>Although removing entities is always a controversial subject (<i>logical</i> 
	 * deletes, vs <i>physical</i> deletes), keep in mind that <i>cascading</i> 
	 * are always honored regardless of the definition of a <i>delete</i> operation. 
	 * @param id the primary identifier of the entity to delete. 
	 */
	public void deleteEntity(PK id);
	
	/**
	 * Finds an entity identified by the primary indentifier. This operation
	 * returns null if the given identifier is null or no such entity exists.
	 * @param id the primary identifier of this entity.
	 * @return the entity, null if none.
	 */
	public T findById(PK id);
	
	/**
	 * Retrieves a collection of all entities in the repository.
	 * <p><b>WARNING</b>: This operation can be a very expensive one depending
	 * on the number of entities in the persistent context. Use with caution.
	 * @return a collection of all entities.
	 */
	public Collection<T> retrieveAll();
}
